import { messages } from "share/common";
import RSCService from '../travel-report/report-search-components.service';
import React from "react";
import {
  getBooksDefaultValue,
  todayYear
} from "../universal-report/universal-report.service";
import { message, Radio, Select } from "antd";

const Option = Select.Option;
import ReportPrivateService from "./report-private.service"
import NewCostCenterSelector from "../universal-report/components/new-cost-center-selector";
import NumberRange from 'containers/financial-management/expense-view/component/number-range';
import departmentObj from 'containers/financial-management/new-finance-audit/searchForm-components/department'
import moment from "moment";

const {
  getValueListCommon,
  getExpenseTypeListByBooksID,
  getERStatusWithDataType,
  getFilterFormOidsByBooksID
} = RSCService;

/**
 * 这个文件仅包含图形化报表的通用逻辑
 * 接口在report-private-service中
 * 报表数据处理在data-transfer中
 *
 * 大部分逻辑与universal-report.service相同，可以视为其简化版
 *
 */

export default {
  codeToLabel: {},
  codeToDependency: {}, // 当前项code => 依赖的项code
  dependencyMap: {},  // 以被依赖项code为key，值为依赖项的code数组，例如company和currency依赖于books，则books: ['company', 'currency']

  // 每次进入新的报表时清空之前保存的map
  resetMaps() {
    this.codeToLabel = {};
    this.codeToDependency = {};
    this.dependencyMap = {};
  },


  //初始化搜索组件数据
  InitSearchComponents({ context }) {
    let reportId = context.state.reportId;
    let list = ReportPrivateService[reportId].searchFormList;
    this.resetMaps();
    return this.searchFormFactory({ list, context })
  },

  searchFormFactory({ list, context, searchFormItem, changeParams }) {

    function CommonMultiSelectParser(id, Field = undefined){ // Field可用于指定某个字段，默认是value字段
      return value => {
        if (value && value.length) {
          return { [id]: value.map(item => Field ? item[Field] : item.value) }
        }
        return { [id]: undefined }
      }
    }

    // 简单的选择类型的筛选器生成方法
    function CommonSelectFactory({ getParams, multiple, getMethod }) {
      return multiple ? ({ label, id }) => {
        return {
          label,
          id,
          component: 'MultiSelector',
          props: {
            selectorItem: {
              service: () => (getMethod || getValueListCommon)(getParams),
              label: 'label',
              key: 'value'
            },
          },
          parser: CommonMultiSelectParser(id)
        }
      } : ({ label, id }) => {
        return {
          label,
          id,
          component: 'Selector',
          props: {
            selectorItem: {
              service: () => (getMethod || getValueListCommon)(getParams),
              label: 'label',
              key: 'value'
            }
          }
        }
      }
    }

    // 简单筛选器的通用生成方法
    function CommonComponentFactory(component = 'Input', parser, formatter) {
      let placeholder;
      if (component === 'Input') {
        placeholder = messages('common.please.input')/*请输入*/;
      }
      return function ({ label, id }) {
        return {
          label,
          id,
          component,
          props: {
            parser,
            formatter,
            placeholder
          }
        }
      }
    }

    // 通用Select及Radio等antd组件tagParser
    function commonTagParser(rowChildren) {
      return value => {
        if (typeof(value) === 'object') {
          let selectedChildren = rowChildren.filter(rowItem => value.find(selectedItem => selectedItem === rowItem.value))
            .map(selectedItem => selectedItem.label)
          return selectedChildren.length <= 3 ? selectedChildren.join(', ') : selectedChildren.slice(0, 3).join(', ') + '...'
        } else {
          return (rowChildren.find(item => item.value === value) || {}).label
        }
      }
    }

    // 依赖帐套的筛选器获取当前帐套id及placeholder的方法
    const setOfBooksIdAndPlaceholderFactory = (context) => {
      let { advancedSearchFormRef } = context;
      let setOfBooksId = getBooksDefaultValue(context).setOfBooksId;

      // 直接从advancedSearchFormRef取值，似乎取不到，或者是修改之前的值
      if (advancedSearchFormRef) {
        let setOfBooksIdWrapper = advancedSearchFormRef.getFieldValue('filterSetOfBooksId');
        if (setOfBooksIdWrapper && setOfBooksIdWrapper[0]) {
          setOfBooksId = setOfBooksIdWrapper[0].setOfBooksId;
        }
      }

      // 从修改值中取值
      if (changeParams && changeParams[0]) {
        setOfBooksId = changeParams[0].setOfBooksId;
      }

      let placeholder = setOfBooksId ? messages('common.select')/*请选择*/ : messages('finance-7.key154')/*请先选择账套*/
      return {
        setOfBooksId,
        placeholder
      }
    };

    // 通用dateRangePicker的[parser, formatter]
    const dateParserAndFormatter = [
      arr => arr ? arr.map(item => item ? moment(item) : undefined) : [],
      (start, end) => {
        if (!start && !end) return undefined
        return [start ? start.format('YYYY-MM-DD') : undefined, end ? end.format('YYYY-MM-DD') : undefined]
      }
    ];

    // 依赖日期类型的筛选器获取当前日期类型的方法
    const dateTypeFactory = (context, changeParams) => {
      if (changeParams) {
        return changeParams.value
      }
      let { advancedSearchFormRef } = context;
      if (advancedSearchFormRef) {
        let filterDateTypeValue = advancedSearchFormRef.getFieldValue('filterDateType') || {};
        return filterDateTypeValue.value
      }
      return '0'
    };

    const { searchFormInitialValueFactory, cascadeHandler } = this;

    // 当前报表私有逻辑载体
    const { currentReportPrivate } = context;
    const {
      searchItemHandler = {},
    } = currentReportPrivate;

    /**
     *
     * 这里的id === code
     * code to search item
     */
    const DEFAULT_CODE_MAP = {
      'filterYear': ({ label, id }) => {
        // 租户创建那一年至今或20年前至今
        let tenantFromFeeReport = context.props.tenant;
        let startYear = (new Date(tenantFromFeeReport.createdDate)).getFullYear();
        let length = tenantFromFeeReport.createdDate ? todayYear - startYear + 10 : 10;
        let children = new Array(length).fill(1).map((val, index) => {
          let year = todayYear - index;
          return <Option key={year}>{year}</Option>
        });
        return {
          label,
          id,
          component: 'Select',
          props: {
            style: { width: '100%' },
            placeholder: messages('common.select')/*请选择*/
          },
          children,
          tagParser: value => value
        }
      },
      'filterExpAnalyzeDateType': ({ label, id }) => {
        const type = [
          { value: '0', name: messages('common.happened.date')/*发生日期*/},
          { value: '1', name: messages('finance-7.key86')/*提交报销日期*/},
          { value: '2', name: messages('finance-7.key87')/*报销单审核通过日期*/},
          { value: '3', name: messages('finance-7.key59')/*付款日期*/ }];
        const children = type.map((item) => <Option key={item.value}>{item.name}</Option>);
        return {
          label,
          id,
          component: 'Select',
          props: {
            style: { width: '100%' },
            mode: 'default',
            placeholder: messages('common.select')/*请选择*/,
            allowClear: false
          },
          children,
          nullValue: [],
          tagParser: value => {
            let name = ''
            type.some(item => {
              if (item.value === value) {
                name = item.name
                return  true;
              }
            });
            return name;
          }
        };
      },
      'filterYearMonths': ({ label, id }) => {
        let children = new Array(12).fill(1).map((val, index) => {
          let month = index + 1;
          return <Option key={month}>{month}</Option>
        });
        return {
          label,
          id,
          component: 'Select',
          props: {
            style: { width: '100%' },
            mode: 'multiple',
            placeholder: messages('common.select')/*请选择*/,
            allowClear: true
          },
          children,
          nullValue: [],
          tagParser: value => {
            if (value.length <= 3) {
              return value.join(', ')
            } else {
              return value.slice(0, 3).join(', ') + '...'
            }
          }
        }
      },
      'filterCompanyOids': ({ label, id }) => {
        let { setOfBooksId, placeholder } = setOfBooksIdAndPlaceholderFactory(context);
        return {
          label,
          id,
          component: 'Chooser',
          props: {
            type: 'auto_audit_add_company',
            labelKey: 'name',
            valueKey: 'companyOID',
            onlyNeed: 'companyOID',
            single: false,
            placeholder,
            listExtraParams: {
              setOfBooksId
            }
          }
        }
      },
      'filterSetOfBooksId': ({ label, id }) => {
        return {
          label,
          id,
          component: 'Chooser',
          props: {
            type: 'select_set_of_books',
            labelKey: 'setOfBooksName_functionalCurrencyCode',
            valueKey: 'setOfBooksId',
            single: true,
            onChange: (e) => cascadeHandler.call(this, 'filterSetOfBooksId')(context, e)
          }
        }
      },
      'recipientTypes': CommonSelectFactory({ getParams: 5047, multiple: true }),
      'filterDateType': ({ label, id }) => {
        let item = CommonSelectFactory({ getParams: 5037 })({ label, id });
        item.props.onChange = (e) => cascadeHandler.call(this, 'filterDateType')(context, e);
        item.props.allowClear = false;
        item.tagUnclosed = true;
        return item
      },
      'filterExpenseTypeIds': ({ label, id }) => {
        const service = () => {
          let { setOfBooksId } = setOfBooksIdAndPlaceholderFactory(context);
          return getExpenseTypeListByBooksID(setOfBooksId)
        };
        return {
          label,
          id,
          component: 'MultiSelector',
          props: {
            selectorItem: {
              service,
              label: 'label',
              key: 'value'
            },
          },
          parser: CommonMultiSelectParser(id)
        }
      },
      'filterFormOids': ({ label, id }) => {
        const service = () => {
          let { setOfBooksId } = setOfBooksIdAndPlaceholderFactory(context);
          let dateType = dateTypeFactory(context, changeParams);
          return getFilterFormOidsByBooksID(setOfBooksId, dateType)
        };
        return {
          label,
          id,
          component: 'MultiSelector',
          props: {
            selectorItem: {
              service,
              label: 'label',
              key: 'value'
            },
          },
          parser: CommonMultiSelectParser(id)
        }
      },
      'filterStatus': ({ label, id }) => {
        const service = () => {
          let dateType = dateTypeFactory(context, changeParams);
          return getERStatusWithDataType(dateType)
        };
        return {
          label,
          id,
          component: 'MultiSelector',
          props: {
            selectorItem: {
              service,
              label: 'label',
              key: 'value'
            },
            getPopupContainer: () => document.body
          },
          parser: CommonMultiSelectParser(id)
        }
      },
      'filterShowYOY': ({ label, id }) => {
        const rowChildren = [
          { label: messages('common.yes')/*是*/, value: true },
          { label: messages('common.no')/*否*/, value: false },
        ];
        const children = rowChildren.map((option) => {
          return <Radio value={option.value} key={option.value}>{option.label}</Radio>
        });
        return {
          label,
          id,
          component: 'RadioGroup',
          children,
          tagParser: commonTagParser(rowChildren)
        }
      },
      'filterIncludeSubDepts': ({ label, id }) => {
        const rowChildren = [
          { label: messages('common.yes')/*是*/, value: true },
          { label: messages('common.no')/*否*/, value: false },
        ];
        const children = rowChildren.map((option) => {
          return <Radio value={option.value} key={option.value}>{option.label}</Radio>
        });
        return {
          label,
          id,
          component: 'RadioGroup',
          children,
          tagParser: commonTagParser(rowChildren)
        }
      },
      'filterDepartmentCodes': ({ label, id }) => {
        return {
          ...departmentObj,
          label,
          id,
          parser: value =>value && value.department && value.department[0] ? {
            [id]: value.department.map(item => item.departmentCode),
            isIncludeSubDept: value.isIncludeChildren === false ? 'N' :'Y'
          } : null,
        }
      },
      'filterApplicantOids': ({ label, id }) => {
        return {
          label,
          id,
          component: 'Chooser',
          props: {
            type: 'user',
            labelKey: 'fullName',
            valueKey: 'userOID',
            onlyNeed: 'userOID',
            single: false,
            listExtraParams: { status: 'all' }
          }
        }
      },
      'filterApprovalOids': ({ label, id }) => {
        return {
          label,
          id,
          component: 'Chooser',
          props: {
            type: 'user',
            labelKey: 'fullName',
            valueKey: 'userOID',
            onlyNeed: 'userOID',
            single: false,
            listExtraParams: { status: 'all' }
          }
        }
      },
      'filterExpOwner': ({ label, id }) => {
        return {
          label,
          id,
          component: 'Chooser',
          props: {
            type: 'user',
            labelKey: 'fullName',
            valueKey: 'userOID',
            onlyNeed: 'userOID',
            single: false,
            listExtraParams: { status: 'all' }
          }
        }
      },
      'searchCostCenterCommands': ({ label, id }) => {
        let { setOfBooksId, placeholder } = setOfBooksIdAndPlaceholderFactory(context);
        return {
          label,
          id,
          component: <NewCostCenterSelector
            title={messages('finance-7.key155')/*成本中心*/}
            setOfBooksId={setOfBooksId}
            placeholder={placeholder}
          />,
          tagParser: value => messages('common.total.selected',{arg1: value.length})/*已选 {arg1} 条*/
        }
      },
      'filterAmountPercent': ({ label, id }) => {
        return {
          label,
          id,
          component: <NumberRange percentFormat allowInputZero />,
          parser: value => ({
            filterPercentageStart: value && (value[0] || value[0] === 0) ? value[0] : undefined,
            filterPercentageEnd: value && (value[1] || value[1] === 0) ? value[1] : undefined
          }),
          tagParser: value => value && ((value[0] || value[0] === 0) || (value[1] || value[1] === 0)) &&
            `${(value[0] || value[0] === 0) ? `${value[0]}%` : ''} ~ ${(value[1] || value[1] === 0) ? `${value[1]}%` : ''}`
        }
      },
      'filterContractTypes': ({ label, id }) => {
        let companyData = context.props.company;
        return {
          label,
          id,
          component: 'Chooser',
          props: {
            labelKey: 'contractTypeName',
            valueKey: 'id',
            type: 'contract_type',
            single: false,
            listExtraParams: { companyId: companyData.id }
          },
          parser: CommonMultiSelectParser(id, 'id')
        }
      },
      'filterContractStatus': ({ label, id }) => {
        // 注释掉的是要剔除的状态
        let statusList = [
          // { value: '1001', label: messages('finance-7.key156')/*编辑中*/ },
          { value: '1002', label: messages('finance-7.key157')/*审批中*/ },
          // { value: '1003', label: messages('common.withdraw')/*撤回*/ },
          { value: '1004', label: messages('finance-7.key158')/*审批通过*/ },
          // { value: '1005', label: messages('finance-7.key159')/*审批驳回*/ },
          // { value: '1006', label: messages('finance-7.key160')/*已删除*/ },
          { value: '6001', label: messages('finance-7.key161')/*暂挂*/ },
          { value: '6002', label: messages('finance-7.key162')/*已取消*/ },
          { value: '6003', label: messages('finance-7.key163')/*已完成*/ },
          // { value: '6004', label: messages('finance-7.key164')/*取消暂挂*/ }, // 只为中间状态取消暂挂后合同状态为审批通过
        ];
        let children = statusList.map(item => <Option key={item.value}>{item.label}</Option>)
        return {
          label,
          id,
          component: 'Select',
          children,
          nullValue: [],
          props: {
            style: { width: '100%' },
            mode: 'multiple',
            placeholder: messages('common.select')/*请选择*/,
            allowClear: true
          },
          tagParser: commonTagParser(statusList)
        }
      },
      'default': CommonComponentFactory(),
      'filterBalanceType': ({ label, id }) => {
        let statusList = [
          { value: '1', label: messages('finance-7.key165')/*审核视角*/ },
          { value: '2', label: messages('finance-7.key166')/*支付视角*/ },
        ];
        let children = statusList.map(item => <Option key={item.value}>{item.label}</Option>)
        return {
          label,
          id,
          component: 'Select',
          children,
          nullValue: [],
          props: {
            style: { width: '100%' },
            placeholder: messages('common.select')/*请选择*/,
            allowClear: false
          },
          tagParser: commonTagParser(statusList),
          tagUnclosed: true
        }
      },
      'filterAuditApprovalDate': CommonComponentFactory("DateRangePicker", ...dateParserAndFormatter)
    };

    // 供initFactory及update方法使用
    const itemFactory = ({ code, label, dependencyCode }) => {
      let mapItem = DEFAULT_CODE_MAP[code] || DEFAULT_CODE_MAP.default;
      let searchItem = mapItem({ label, id: code, dependencyCode });

      // 通用初始化值处理
      let initialValueFactory = searchFormInitialValueFactory[code];
      if (initialValueFactory) {
        searchItem.initialValue = typeof initialValueFactory === 'function'
          ? initialValueFactory({ context, code, label })
          : initialValueFactory;
      }

      // 各报表针对筛选项初始化处理的私有逻辑
      if (searchItemHandler[code]) {
        searchItem = searchItemHandler[code](searchItem)
      }

      return searchItem
    };

    // 初次时生成searchItem的方法
    // 与update方法的区别在于做了些初始化工具的步骤
    const initFactory = (item) => {
      let {
        code,
        label,
        dependencyCode,
      } = item;

      this.codeToLabel[name] = label;

      // 收集code依赖
      if (dependencyCode) {
        if (Array.isArray(this.dependencyMap[dependencyCode])) {
          this.dependencyMap[dependencyCode].push(code);
        } else {
          this.dependencyMap[dependencyCode] = [code];
        }
        this.codeToDependency[code] = dependencyCode;
      }

      return itemFactory({ code, label, dependencyCode })
    };

    // 级联更新searchItem时的方法
    const update = (item) => {
      let { id: code, label } = item;
      let dependencyCode = this.codeToDependency[code];
      return itemFactory({ code, label, dependencyCode })
    };

    if (searchFormItem) {
      return update(searchFormItem)
    } else {
      return list.map((item) => initFactory(item));
    }
  },

  // 级联处理入口
  cascadeHandler(code) {
    const cascadeHandlerMap = {
      'filterSetOfBooksId': (context, e) => {
        let depArr = this.dependencyMap['filterSetOfBooksId'];
        if (!depArr || !depArr.length) return;
        let { advancedSearchFormRef } = context;
        this.commonCascadeHandler({ context, e, code: 'filterSetOfBooksId', advancedSearchFormRef });

        let oldValue = advancedSearchFormRef.getFieldValue('filterSetOfBooksId');
        if (oldValue && oldValue[0]) {
          message.warn(messages('finance-7.key167')/*请重选依赖账套的搜索条件*/);
        }
      },
      'filterDateType': (context, e) => {
        let depArr = this.dependencyMap['filterDateType'];
        if (!depArr || !depArr.length) return;
        let { advancedSearchFormRef } = context;
        this.commonCascadeHandler({ context, e, code: 'filterDateType', advancedSearchFormRef });
      },
    };
    return cascadeHandlerMap[code]
  },

  commonCascadeHandler({ context, e, code, advancedSearchFormRef }) {
    let depArr = this.dependencyMap[code];
    if (!depArr || !depArr.length) return;
    let { searchForm } = context.state;
    let resetObject = {};
    depArr.forEach(code => {
      let { value, index } = this.getSearchItemFromSearchFormByCode(searchForm, code);
      searchForm[index] = this.searchFormFactory({ context, searchFormItem: value, changeParams: e });
      resetObject[code] = undefined;
    });
    context.setState({
      searchForm
    }, () => {
      advancedSearchFormRef.setFieldsValue(resetObject)
    });
  },

  // 初始值，如果是函数则会传入context执行
  searchFormInitialValueFactory: {
    'filterYear': `${todayYear}`,
    'filterSetOfBooksId': ({ context }) => [getBooksDefaultValue(context)],
    'filterDateType': { value: "0", label: messages('finance-7.key103')/*费用发生日期*/ },
    'filterShowYOY': true,
    'filterIncludeSubDepts': true,
    'filterExpAnalyzeDateType': '0',
    'filterBalanceType': '2'
  },

  getSearchItemFromSearchFormByCode(searchForm, code) {
    let result = {
      value: undefined,
      index: undefined
    };
    result.value = searchForm.find((item, index) => item.id === code && ((result.index = index) || true));
    return result;
  },
  /**
   * 搜索之前的校验及数据转换
   * @param params
   * @param context
   */
  searchParamsTransfer({ params, context }) {
    let keys = Object.keys(params);
    let length = keys.length;
    let index = 0;
    let result = {};
    let error;


    // 返回true则表示校验失败，停止搜索
    const validateCodeMap = {
      'filterSetOfBooksId': ({ value }) => {
        if (!value || !value.length) {
          return messages('finance-7.key168')/*账套不能为空*/
        }
      },
      'filterYear': ({ value }) => {
        if (!value) {
          return messages('finance-7.key169')/*请选择年份*/
        }
      },
    };

    // code为key的转换器map，优先级高于commonTransfer
    const transferMap = {
      'filterSetOfBooksId': ({ value }) => {
        if (value && value.length) {
          return value[0].setOfBooksId
        } else {
          return ''
        }
      },
      'filterYearMonths': ({ value }) => value && value.length ? value : undefined,
      'filterAuditApprovalDate': ({value}) => value ? JSON.stringify(value) : undefined
    };

    try {
      while (index < length) {
        let code = keys[index];
        let value = params[code];
        let label = this.codeToLabel[code];

        let validate = validateCodeMap[code];
        // 依据code的validate
        if (validate) {
          error = validate({ value, params, label });
          if (error) {
          //最末已经统一返回处理了，这里再弹出一下，就会弹出两次了
          //message.warn(error);
            break;
          }
        }

        let transfer = transferMap[code];

        // transfer
        if (transfer) {
          result[code] = transfer({ code, value });
        } else {
          result[code] = value;
        }
        index++;
      }

      return error ? Promise.reject({ type: "validateError", message: error }) : Promise.resolve(result);
    } catch (e) {
      return Promise.reject(e);
    }
  },

  /**
   * 仅做数据转换，不做校验，用于报表导出
   * @param params
   * @param context
   */
  searchParamsTransferSync({ params, context }) {
    let keys = Object.keys(params);
    let length = keys.length;
    let index = 0;
    let result = {};
    // code为key的转换器map，优先级高于commonTransfer
    const transferMap = {
      'filterSetOfBooksId': ({ value }) => {
        if (value && value.length) {
          return value[0].setOfBooksId
        } else {
          return ''
        }
      },
      'filterYearMonths': ({ value }) => value && value.length ? value : undefined,
      'filterAuditApprovalDate': ({value}) => value && value.length ? JSON.stringify(value) : undefined
    };

    while (index < length) {
      let code = keys[index];
      let value = params[code];

      let transfer = transferMap[code];

      // transfer
      if (transfer) {
        result[code] = transfer({ code, value });
      } else {
        result[code] = value;
      }
      index++;
    }

    return result;
  },

  /**
   * 获取当前的搜索参数
   * @param context
   */
  getCurrentTransferredParams({context}) {
    const { searchParams, activeChartsParams } = context.state;
    const params = Object.assign({}, searchParams, activeChartsParams);
    return this.searchParamsTransferSync({ params, context });
  }
}
